// --------------------------------------------------------------------------------------------------------------------
// <copyright file="DBResourceHelpers.cs" company="Open Trader">
//   Copyright (c) David Denis (david.denis@systemathics.com)
// </copyright>
// <summary>
//   |  Open Trader - The Open Source Systematic Trading Platform
//   |
//   |  This program is free software: you can redistribute it and/or modify
//   |  it under the terms of the GNU General Public License as published by
//   |  the Free Software Foundation, either version 2 of the License, or
//   |  (at your option) any later version.
//   |
//   |  This program is distributed in the hope that it will be useful,
//   |  but WITHOUT ANY WARRANTY; without even the implied warranty of
//   |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   |  GNU General Public License for more details.
//   |
//   |  You should have received a copy of the GNU General Public License
//   |  along with this program.  If not, see http://www.gnu.org/licenses
//   |
//   |  Up to date informations about Open Trader can be found at :
//   |    http://opentrader.org
//   |    http://opentrader.codeplex.com
//   |
//   |  For professional services, please visit us at :
//   |    http://www.systemathics.com
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Org.OpenTrader.Framework.DataModel
{
    #region

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;

    using Org.OpenTrader.Framework.LiveObjects;
    using Org.OpenTrader.Framework.LiveObjects.Interfaces;

    #endregion

    /// <summary>
    /// The db resource helpers.
    /// </summary>
    public class DBResourceHelpers
    {
        #region Constants and Fields

        /// <summary>
        /// The Identity.
        /// </summary>
        private static readonly Identity Identity = Identity.Create(MethodBase.GetCurrentMethod());

        #endregion

        #region Public Methods

        /// <summary>
        /// The create.
        /// </summary>
        /// <param name="resource">
        /// The resource.
        /// </param>
        /// <returns>
        /// </returns>
        public static IResource Create(DBResource resource)
        {
            var d = new Resource();
            d.Guid = resource.ID;
            d.Name = resource.Name;
            d.Directory = resource.Directory;
            d.Extension = resource.Extension;
            d.Content = resource.Content;
            d.TimeStamp = resource.TimeStamp;
            d.IsAssembly = resource.IsAssembly;
            return d;
        }

        /// <summary>
        /// The destroy resources.
        /// </summary>
        /// <param name="g">
        /// The g.
        /// </param>
        /// <returns>
        /// The destroy resources.
        /// </returns>
        public static bool DestroyResources(Guid g)
        {
            var dbResources = from r in Singleton<DBFramework>.Instance.Entities.DBResource where r.ID == g select r;

            if (dbResources.Count() > 0)
            {
                var dbResource = dbResources.First();
                Singleton<DBFramework>.Instance.Entities.DeleteObject(dbResource);
            }

            var n = Singleton<DBFramework>.Instance.Commit();

            return n > 0;
        }

        /// <summary>
        /// The destroy resources.
        /// </summary>
        /// <param name="directory">
        /// The directory.
        /// </param>
        /// <returns>
        /// The destroy resources.
        /// </returns>
        public static bool DestroyResources(string directory)
        {
            var dbResources = from r in Singleton<DBFramework>.Instance.Entities.DBResource
                              where r.Directory.StartsWith(directory)
                              select r;

            foreach (var dbResource in dbResources)
            {
                Singleton<DBFramework>.Instance.Entities.DeleteObject(dbResource);
            }

            var n = Singleton<DBFramework>.Instance.Commit();

            return n > 0;
        }

        /// <summary>
        /// The get all resources in directory.
        /// </summary>
        /// <param name="directory">
        /// The directory.
        /// </param>
        /// <returns>
        /// </returns>
        public static IDictionary<Guid, DBResource> GetAllResourcesInDirectory(string directory)
        {
            IDictionary<Guid, DBResource> result = new Dictionary<Guid, DBResource>();

            var query = from r in Singleton<DBFramework>.Instance.Entities.DBResource
                        where r.Directory.StartsWith(directory)
                        orderby r.Directory ascending
                        select r;

            foreach (var resource in query)
            {
                result.Add(resource.ID, resource);
            }

            return result;
        }

        /// <summary>
        /// The get resource by path.
        /// </summary>
        /// <param name="path">
        /// The path.
        /// </param>
        /// <returns>
        /// </returns>
        public static DBResource GetResourceByPath(string path)
        {
            var dir = PathUtil.Cleanup(Path.GetDirectoryName(path));
            var name = Path.GetFileName(path);

            var query = from r in Singleton<DBFramework>.Instance.Entities.DBResource
                        where r.Directory.StartsWith(dir)
                        where r.Name == name
                        select r;

            if (query.Count() > 0)
            {
                return query.First();
            }

            return null;
        }

        /// <summary>
        /// truc
        /// </summary>
        /// <param name="directory">
        /// </param>
        /// <param name="resources">
        /// </param>
        /// <returns>
        /// The register.
        /// </returns>
        public static Status Register(string directory, IList<string> resources)
        {
            directory = PathUtil.Cleanup(directory);

            foreach (var resource in resources)
            {
                var name = Path.GetFileName(resource);
                var extension = Path.GetExtension(resource);
                byte[] buffer = null;

                try
                {
                    using (var fs = File.OpenRead(resource))
                    {
                        buffer = new byte[fs.Length];
                        fs.Read(buffer, 0, (int)fs.Length);
                        fs.Close();
                    }
                }
                catch
                {
                    Stdout.WriteLine(string.Format("Wasn't able to load resource {0}, skipping", resource));
                    continue;
                }

                var dbResources = from r in Singleton<DBFramework>.Instance.Entities.DBResource
                                  where r.Name == name
                                  where r.Directory.StartsWith(directory)
                                  select r;

                DBResource dbResource;

                if (dbResources.Count() > 0)
                {
                    Stdout.WriteLine(string.Format("Updating resource {0} in {1}", resource, directory));
                    dbResource = dbResources.First();
                }
                else
                {
                    Stdout.WriteLine(string.Format("Registering new resource {0} in {1}", resource, directory));
                    dbResource = DBResource.CreateDBResource(
                        Guid.NewGuid(), directory, name, extension, buffer, Timings.Now, false);

                    Singleton<DBFramework>.Instance.Entities.AddToDBResource(dbResource);
                }

                dbResource.Content = buffer;
            }

            var n = Singleton<DBFramework>.Instance.Commit();

            if (n > 0)
            {
                return Status.Success(Identity);
            }
            else
            {
                return Status.Failure(Identity, "Commit saved 0 change");
            }
        }

        #endregion
    }
}